﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.Common;
using System.Data.Entity;
using System.Data;
using System.Linq.Expressions;

namespace Infrastructure.Common.Data
{
    /// <summary>
    /// Base repository class. Inherit from this class and implement the abstract methods for Add, Update, Delete and Get Methods.
    /// </summary>
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
    public abstract class Repository<TEntity> : IRepository<TEntity>
        where TEntity : class
    {
        /// <summary>
        /// Gets or sets the databse context.
        /// </summary>
        /// <value>
        /// The context.
        /// </value>
        protected Context Context { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="Repository&lt;TEntity&gt;"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        public Repository(IContext context)
        {
            // try to use the provided context as a compatible context
            // this is wrong, I see that now, no use in having a container etc, this repository is tied to
            // a specific context class.
            this.Context = context as Context;

            if (Context == null)
            {
                throw new Exception("The provided context is not compatible with this repository");
            }
        }

        /// <summary>
        /// Adds the specified item to the data context.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <returns></returns>
        public abstract TEntity Add(TEntity item);

        /// <summary>
        /// Updates the specified item in the attached data context.
        /// </summary>
        /// <param name="item">The item.</param>
        public abstract void Update(TEntity item);

        /// <summary>
        /// Deletes the specified item from the attached context.
        /// </summary>
        /// <param name="item">The item.</param>
        public abstract void Delete(TEntity item);

        /// <summary>
        /// Gets items from the attached context that match the specified predicates.
        /// </summary>
        /// <param name="predicates">The predicates.</param>
        /// <returns><see cref="IEnumerable<TEntity>"/></returns>
        public abstract IEnumerable<TEntity> Get(params Expression<Func<TEntity, bool>>[] predicates);

        /// <summary>
        /// Saves this instance.
        /// </summary>
        public void Save()
        {
            this.Context.SaveChanges();
        }
    }
}
